<?php
declare (strict_types=1);

namespace app\admin\controller;

use addons\Builder\facade\Builder;
use app\common\model\Area;
use app\common\model\Express;
use app\common\model\OrderProduct;
use app\common\tool\Result;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use think\exception\ValidateException;
use think\facade\View;
use think\Response;

class Order extends Base
{
    //主键，默认为id
    protected string $pk = 'id';

    //主模型
    protected string $model = '\app\common\model\Order';

    //关联模型
    protected array $hasOne = ['user', 'p', 'c', 'd', 'express', 'productsField'];

    protected array $append = ['status_name'];

    //自定义方法排序
    protected array $sort = ['id' => 'desc'];

    public function index(): string
    {
        return Builder::Table()
            ->addColumn(['fixed' => 'left', 'title' => '全选', 'type' => 'checkbox'])
            ->addColumn(['field' => 'id', 'title' => 'ID', 'sort' => true, 'width' => 80])
            ->addColumn(['field' => 'sn', 'title' => '订单号', 'templet' => '#snTpl', 'width' => 200])
            ->addColumn(['field' => 'uid', 'title' => '下单会员', 'templet' => '#_userTpl', 'width' => 240])
            ->addColumn(['field' => 'product', 'title' => '订单商品', 'templet' => '#productTpl', 'width' => 300])
            ->addColumn(['field' => 'total_amount', 'title' => '商品总金额', 'width' => 100])
            ->addColumn(['field' => 'real_amount', 'title' => '实付金额', 'width' => 100])
            ->addColumn(['field' => 'create_time', 'title' => '下单时间', 'width' => 150])
            ->addColumn(['field' => 'status_name', 'title' => '状态', 'width' => 100])
            ->addColumn(['field' => 'receiver', 'title' => '收货人', 'width' => 100])
            ->addColumn(['field' => 'receiver_tel', 'title' => '收货人联系方式', 'width' => 100])
            ->addColumn(['field' => 'address', 'title' => '收货地址', 'templet' => '#addressTpl', 'width' => 300])
            ->addColumn(['field' => 'pay_time', 'title' => '支付时间', 'width' => 150])
            ->addColumn(['field' => 'pay_way', 'title' => '支付方式', 'width' => 100])
            ->addColumn(['field' => 'post_time', 'title' => '发货时间', 'width' => 150])
            ->addColumn(['fixed' => 'right', 'align' => 'center', 'toolbar' => '#orderDemo', 'title' => '操作', 'width' => 180])
            ->addRightButtons([
                'edit' => [
                    'title' => '详情',
                    'unity_title' => '订单详情',
                    'size' => '60%'
                ],
                'deliver' => [
                    'title' => '发货',
                    'url' => url('Order/deliver')->build()
                ],
                'delete'
            ])
            ->addTopButtons([
                'exportOrder' => [
                    'title' => '导出订单',
                    'class' => 'cyan',
                    'icon' => 'layui-icon-export',
                    'url' => url('order/exportOrder')->build(),
                    'event' => '_exportOrder',
                ],
                'exportPower' => [
                    'title' => '导出发货单',
                    'class' => 'cyan',
                    'icon' => 'layui-icon-export',
                    'url' => url('order/exportOrder')->build() . '?type=invoice',
                    'event' => '_exportOrder',
                ],
                'import' => [
                    'title' => '上传发货单发货',
                    'class' => 'normal import-boost',
                    'icon' => 'layui-icon-upload',
                    'url' => url('order/importDeliver')->build(),
                    'event' => '_import',
                    'init' => true
                ]
            ])
            ->addLineStyle('height: 65px;')
            ->addSearch([
                ['sn', '订单编号', 'input,Like'],
                ['uid', '会员编号/昵称/手机号', 'input,Like', '', '\app\common\model\User', 'code|nickname|mobile,id'],
                ['id', '商品名称', 'input,Like', '', '\app\common\model\OrderProduct', 'title,order_id'],
                ['status', '状态', 'select', getOrderStatus()]
            ])
            ->addExtraHtml(['order'])
            ->fetch();
    }

    public function edit($id = '', $tpl = 'order/edit', $info = ''): string
    {
        return parent::edit($id, $tpl, $info);
    }

    public function deliver($id = ''): Response|string
    {
        if ($this->request->isPost()) {
            $param = $this->request->post();
            try {
                $this->validate($param, 'OrderDeliver');
            } catch (ValidateException $e) {
                return Result::fail($e->getError());
            }
            return Result::fastReturn($this->model::deliver($param, $this->admin));
        }
        $info = $this->model::where(['id' => $id])->find();
        View::assign([
            'express' => Express::where(['status' => 1])->order('sort desc')->select(),
            'info' => $info
        ]);

        return View::fetch();
    }

    public function exportOrder(): Response
    {
        $param = $this->request->get();
        $that = $this->model::with($this->hasOne);
        $map = [];
        if (!empty($param['tableExportIds'])) {
            $that->whereIn('id', $param['tableExportIds']);
        } else {
            if (!empty($param['sn'])) {
                $map['sn'] = trim($param['sn']);
            }
            if (!empty($param['status'])) {
                $map['status'] = $param['status'];
            }
            if (!empty($param['uid'])) {
                $uids = \app\common\model\User::where('code|nickname|mobile', trim($param['uid']))->column('id');
                if ($uids) {
                    $that->whereIn('uid', $uids);
                }
            }
            if (!empty($param['create_time'])) {
                [$start, $end] = explode(' - ', $param['create_time']);
                $that->whereBetweenTime('create_time', strtotime($start), strtotime($end) + 86399);
            }
            if (!empty($param['id'])) {
                $order_ids = OrderProduct::whereLike('title', '%' . trim($param['id']) . '%')->column('order_id');
                if ($order_ids) {
                    $that->whereIn('id', $order_ids);
                }
            }
        }
        $field = 'id,sn,uid,num as total_num,total_amount,real_amount,receiver,receiver_tel,province,city,district,address_details,
        remark,status,pay_way,pay_time,create_time';
        if (!empty($param['type']) && $param['type'] == 'invoice') {
            $map['status'] = 2;
            $express_name = '';
            $express_code = '';
            $title = '发货单';
        } else {
            $field .= ',express_id,express_code,post_time,receipt_time,finish_time';
            $express_name = 'express_name';
            $express_code = 'express_code';
            $title = '订单列表';
        }
        if ($map) {
            $that->where($map);
        }
        $list = $that->field($field)->order('id', 'desc')->append($this->append)->select();
        $calls = [
            ['call' => 'A', 'title' => '订单ID', 'width' => 10, 'marge' => true, 'field' => 'id'],
            ['call' => 'B', 'title' => '订单编号', 'width' => 25, 'marge' => true, 'field' => 'sn'],
            ['call' => 'C', 'title' => '物流公司编码', 'width' => 20, 'marge' => true, 'field' => ''],
            ['call' => 'D', 'title' => '物流公司', 'width' => 20, 'marge' => true, 'field' => $express_name],
            ['call' => 'E', 'title' => '物流单号', 'width' => 30, 'marge' => true, 'field' => $express_code],
            ['call' => 'F', 'title' => '会员编号', 'width' => 15, 'marge' => true, 'field' => 'code'],
            ['call' => 'G', 'title' => '会员昵称', 'width' => 15, 'marge' => true, 'field' => 'nickname'],
            ['call' => 'H', 'title' => '会员手机号', 'width' => 15, 'marge' => true, 'field' => 'mobile'],
            ['call' => 'I', 'title' => '收货人姓名', 'width' => 15, 'marge' => true, 'field' => 'receiver'],
            ['call' => 'J', 'title' => '收货人联系方式', 'width' => 20, 'marge' => true, 'field' => 'receiver_tel'],
            ['call' => 'K', 'title' => '收货地址', 'width' => 70, 'marge' => true, 'field' => 'address'],
            ['call' => 'L', 'title' => '商品名称', 'width' => 60, 'marge' => false, 'field' => 'title'],
            ['call' => 'M', 'title' => '商品规格', 'width' => 20, 'marge' => false, 'field' => 'spec'],
            ['call' => 'N', 'title' => '商品单价', 'width' => 15, 'marge' => false, 'field' => 'vip_price'],
            ['call' => 'O', 'title' => '商品数量', 'width' => 15, 'marge' => false, 'field' => 'num'],
            ['call' => 'P', 'title' => '商品总数量', 'width' => 15, 'marge' => true, 'field' => 'total_num'],
            ['call' => 'Q', 'title' => '商品总金额', 'width' => 15, 'marge' => true, 'field' => 'total_amount'],
            ['call' => 'R', 'title' => '实付金额', 'width' => 15, 'marge' => true, 'field' => 'real_amount'],
            ['call' => 'S', 'title' => '订单备注', 'width' => 20, 'marge' => true, 'field' => 'remark'],
            ['call' => 'T', 'title' => '支付时间', 'width' => 20, 'marge' => true, 'field' => 'pay_time'],
            ['call' => 'U', 'title' => '下单时间', 'width' => 20, 'marge' => true, 'field' => 'create_time']
        ];
        if (empty($param['type'])) {
            $calls = array_merge($calls, [
                ['call' => 'V', 'title' => '状态', 'width' => 20, 'marge' => true, 'field' => 'status_name'],
                ['call' => 'W', 'title' => '发货时间', 'width' => 20, 'marge' => true, 'field' => 'post_time'],
                ['call' => 'X', 'title' => '收货时间', 'width' => 20, 'marge' => true, 'field' => 'receipt_time'],
                ['call' => 'Y', 'title' => '完成时间', 'width' => 20, 'marge' => true, 'field' => 'finish_time']
            ]);
        }
        $newExcel = new Spreadsheet();
        $objSheet = $newExcel->getActiveSheet();
        $objSheet->setTitle($title)->getRowDimension(1)->setRowHeight(30);
        foreach ($calls as $call) {
            $objSheet->setCellValue("{$call['call']}1", $call['title']);
            $objSheet->getColumnDimension($call['call'])->setWidth($call['width']);
        }
        $baseRow = 2;
        $baseMerge = 0;
        $cell = 2;
        $end = 2;
        foreach ($list as $val) {
            $margeI = $baseMerge + $baseRow;
            $count = count($val->productsField);
            if ($count > 1) {
                $merge = $margeI + $count - 1;
                foreach ($calls as $call) {
                    if (!$call['marge']) continue;
                    $objSheet->mergeCells("{$call['call']}{$margeI}:{$call['call']}{$merge}");
                }
            }
            $baseMerge += $count;
            foreach ($val->productsField as $product) {
                foreach ($calls as $call) {
                    if ($call['marge']) continue;
                    $objSheet->setCellValue($call['call'] . $cell, $product[$call['field']]);
                }
                $objSheet->getRowDimension($cell)->setRowHeight(30);
                $cell += 1;
            }
            $p = $val->p ? $val->p->title : '';
            $c = $val->c ? $val->c->title : '';
            $d = $val->d ? $val->d->title : '';
            foreach ($calls as $call) {
                if (!$call['marge']) continue;
                $value = !$call['field'] ? "" : match ($call['field']) {
                    'supplier_name' => $val->supplier ? $val->supplier->title : '',
                    'express_name' => $val->express ? $val->express->title : '',
                    'code' => $val->user->code,
                    'nickname' => $val->user->nickname,
                    'mobile' => $val->user->mobile,
                    'address' => $p . $c . $d . $val->address_details,
                    default => $val[$call['field']]
                };
                $objSheet->setCellValue($call['call'] . $end, $value);
            }
            $end += $count;
        }
        $end = $calls[count($calls) - 1]['call'];
        $objSheet->getStyle("A1:{$end}1")->applyFromArray([
            'font' => [
                'bold' => true,
                'color' => [
                    'rgb' => '000000'
                ],
                'size' => 12,
            ]
        ]);
        $objSheet->getStyle('A1:' . $end . $cell - 1)->applyFromArray([
            'alignment' => [
                'horizontal' => Alignment::HORIZONTAL_CENTER,
                'vertical' => Alignment::VERTICAL_CENTER,
            ],
            'borders' => [
                'outline' => [
                    'borderStyle' => Border::BORDER_THIN,
                    'color' => ['argb' => '000000'],
                ],
                'inside' => [
                    'borderStyle' => Border::BORDER_THIN,
                    'color' => ['argb' => '000000'],
                ]
            ],
        ]);
        $objWriter = IOFactory::createWriter($newExcel, 'Xlsx');
        $path = '/download/' . $title . date('Y_m_d_H_i_s') . '.xlsx';
        $objWriter->save(app()->getRootPath() . 'public' . $path);

        return Result::success('正在下载...', $path);
    }

    public function exportPower(): Response
    {
        $param = $this->request->get();
        $that = $this->model::with($this->hasOne)->where(['status' => 2]);
        $map = [];
        if (!empty($param['tableExportIds'])) {
            $that->whereIn('id', $param['tableExportIds']);
        } else {
            if (!empty($param['sn'])) {
                $map['sn'] = trim($param['sn']);
            }
            if (!empty($param['uid'])) {
                $uids = \app\common\model\User::where('code|nickname|mobile', trim($param['uid']))->column('id');
                if ($uids) {
                    $that->whereIn('uid', $uids);
                }
            }
            if (!empty($param['create_time'])) {
                [$start, $end] = explode(' - ', $param['create_time']);
                $that->whereBetweenTime('create_time', strtotime($start), strtotime($end) + 86399);
            }
            if (!empty($param['id'])) {
                $order_ids = OrderProduct::whereLike('title', '%' . trim($param['id']) . '%')->column('order_id');
                if ($order_ids) {
                    $that->whereIn('id', $order_ids);
                }
            }
        }
        if ($map) {
            $that->where($map);
        }
        $list = $that->select();
        $title = ['ID', '订单编号', '物流公司编码', '物流公司', '物流单号', '相关会员', '订单商品', '商品总金额', '实付金额', '下单时间', '支付时间', '支付方式', '收货人姓名', '收货人手机号', '收货地址'];
        $data = [];
        foreach ($list as $info) {
            $userInfo = $info->user ? $info->user->code . '-' . $info->user->nickname . '-' . $info->user->mobile : '-';
            $products = OrderProduct::where(['order_id' => $info->id])->field('pid,title,spec,num')->select()->toArray();
            $info->product = '';
            foreach ($products as $item) {
                $info->product .= $item['title'] . '-' . $item['spec'] . ' 数量：' . $item['num'] . "\n";
            }
            $p = $info->p ? $info->p->title : '';
            $c = $info->c ? $info->c->title : '';
            $d = $info->d ? $info->d->title : '';
            $address = $p . $c . $d . $info->address_details;
            $data[] = [
                $info->id,
                $info->sn . "\t\n",
                '',
                '',
                '',
                $userInfo,
                $info->product,
                $info->total_amount,
                $info->real_amount,
                $info->create_time,
                $info->pay_time,
                $info->pay_way,
                $info->receiver,
                $info->receiver_tel . "\t\n",
                $address
            ];
        }

        return Result::fastReturn(['code' => 1, 'msg' => 'success', 'name' => '发货单', 'title' => $title, 'data' => $data]);
    }

    public function importDeliver(): Response
    {
        return Result::fastReturn($this->model::importDeliver($this->request->post('file'), $this->admin));
    }

    public function getArea($id, $level = 0): object
    {
        return Area::getArea($id ?: 0, $level);
    }
}